package org.example.system.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.jsonwebtoken.Claims;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.example.system.common.constant.SecurityConstants;
import org.example.system.common.result.Result;
import org.example.system.config.properties.JwtProperties;
import org.example.system.model.entity.Tenant;
import org.example.system.model.form.TenantForm;
import org.example.system.service.JwtService;
import org.example.system.service.TenantService;
import org.modelmapper.ModelMapper;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Tag(name = "小程序-微信授权登录")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/wx")
public class WxLoginController {

    private final TenantService tenantService;

    private final ModelMapper modelMapper;

    private final JwtService jwtService;

    private final RedisTemplate<String, Object> redisTemplate;

    private final JwtProperties jwtProperties;

    private final WxMaService wxMaService;

    @Operation(summary = "租户微信授权登录")
    @PostMapping("/login")
    public Result authLogin(
            @RequestParam(value = "code") String code) throws WxErrorException {
        WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
        if (session != null && StringUtils.hasText(session.getOpenid())) {
            String openid = session.getOpenid();
            LambdaQueryWrapper<Tenant> criteria = new LambdaQueryWrapper<>();
            criteria.eq(Tenant::getOpenId, openid);
            Optional<Tenant> tenantOpt = tenantService.getOneOpt(criteria);

            Tenant tenantEntity;
            if (tenantOpt.isPresent()) {
                tenantEntity = tenantOpt.get();
            } else {
                // 创建新租户

                tenantEntity = new Tenant();
                tenantEntity.setOpenId(openid);
                tenantEntity.setNickName(generateRandomNickName());
                tenantEntity.setAvatarUrl("https://rentcar-bucket.oss-cn-beijing.aliyuncs.com/image/f28d67cd45e8f263b08840fe14768176.png");
                tenantEntity.setCreateTime(LocalDateTime.now());
                tenantEntity.setStatus(0);
                tenantService.save(tenantEntity);
            }

            // 服务端会签发一个 Token，再把这个 Token 发送给客户端
            String accessToken = jwtService.createJwt(openid);
            tenantEntity.setAccessToken(accessToken);
            String key = SecurityConstants.AUTH_LOGIN_KEY_PREFIX + openid;
            redisTemplate.opsForValue().setIfAbsent(key, tenantEntity,
                    jwtProperties.getExpire(), TimeUnit.SECONDS);
            return Result.success(tenantEntity);
        }
        return Result.failed("授权登录失败！");
    }



    @Operation(summary = "更新用户信息(根据openid)")
    @PostMapping(value = "/updateUserInfo")
    public Result updateUserInfo(@RequestBody TenantForm tenantForm) {
        // 1. 获取租户信息
        Tenant tenant = tenantService.getTenantByOpenId(tenantForm.getOpenId());
        System.out.println("_______"+tenant.getAccessToken());

        if (tenant == null) {
            return Result.failed("租户不存在");
        }

        // 2. 保存数据库中获取的 tenant 的 id
        Integer id = tenant.getId();

        // 3. 将 tenantForm 的非空属性映射到现有的 tenant 实例
        modelMapper.map(tenantForm, tenant);

        // 4. 恢复 id 值，确保不丢失
        tenant.setId(id);

        // 5. 更新数据库中的数据
        tenantService.updateById(tenant);

        // 6. 更新 Redis 缓存
        String key = SecurityConstants.AUTH_LOGIN_KEY_PREFIX + tenant.getOpenId();
        redisTemplate.opsForValue().set(key, tenant, jwtProperties.getExpire(), TimeUnit.SECONDS);

        return Result.success(tenant);
    }




    @Operation(summary = "绑定手机号")
    @PostMapping("/bindPhone")
    public Result bindPhone(@RequestParam(value = "code") String code,
                            @RequestParam(value = "openid") String openid) throws WxErrorException {
        WxMaPhoneNumberInfo newPhoneNoInfo = this.wxMaService.getUserService().getNewPhoneNoInfo(code);
        String phone = newPhoneNoInfo.getPurePhoneNumber();
        Tenant tenant = tenantService.getTenantByOpenId(openid);
        tenant.setPhone(phone);
        tenantService.updateById(tenant);
        return Result.success(tenant);
    }

    @Operation(summary = "刷新数据")
    @GetMapping("/refresh")
    public Result getLatestTenantInfo(@RequestHeader("Authorization") String token) {
        String accessToken  = token;
        if (token.startsWith("Bearer ")) {
            accessToken = token.substring(7);
        }
        System.out.println("token"+token);
        // 1. 校验并解析 Token
        Claims claims;
        try {
            claims = jwtService.parseJwt(token); // 解析 Token
        } catch (RuntimeException e) {
            return Result.failed(e.getMessage()); // 捕获并返回 Token 异常信息
        }

        // 2. 获取 Token 中的 openid
        String openid = claims.getSubject(); // openid 存储在 subject 中

        // 3. 查询数据库中的租户信息
        QueryWrapper<Tenant> criteria = new QueryWrapper<>();
        criteria.eq("open_id", openid);
        Tenant tenantEntity = tenantService.getOne(criteria);

        tenantEntity.setAccessToken(accessToken);

        return Result.success(tenantEntity); // 返回最新的租户信息
    }

    private static String generateRandomNickName() {
        // 获取当前时间的小时和分钟
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HHmm");
        String timeStr = LocalDateTime.now().format(formatter);

        // 随机数生成器
        Random random = new Random();
        int randomNum = random.nextInt(100); // 生成 0~99 的随机数

        // 拼接 nickname
        return "客户_" + timeStr + String.format("%02d", randomNum);
    }


}